package com.ppc.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.ppc.constant.ClaimerTypeConstant;
import com.ppc.constant.MessageConstant;
import com.ppc.constant.StatusConstant;
import com.ppc.constant.UserConstant;
import com.ppc.context.BaseContext;
import com.ppc.dto.AdminLoginDTO;
import com.ppc.dto.ClaimSolveDTO;
import com.ppc.dto.ComplaintSolveDTO;
import com.ppc.entity.AdminPPC;
import com.ppc.entity.Claim;
import com.ppc.entity.Complaint;
import com.ppc.entity.Employer;
import com.ppc.entity.Recording;
import com.ppc.entity.Requirement;
import com.ppc.entity.Task;
import com.ppc.entity.TempTask;
import com.ppc.entity.Worker;
import com.ppc.exception.LoginFailedException;
import com.ppc.exception.PasswordErrorException;
import com.ppc.mapper.admin.AdminMapper;
import com.ppc.result.PageResult;
import com.ppc.service.AdminService;
import com.ppc.vo.AdminClaimDetailVO;
import com.ppc.vo.AdminClaimPageVO;
import com.ppc.vo.AdminComplaintDetailVO;
import com.ppc.vo.AdminComplaintPageVO;
import com.ppc.vo.AdminLoginVO;
import com.ppc.vo.EmployerPageVO;
import com.ppc.vo.WorkerPageVO;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

/**
 * @author dy
 * @date 2023/12/20
 * @desciption admin服务层
 */
@Service
public class AdminServiceImp implements AdminService {


  @Autowired
  private AdminMapper adminMapper;

  /**
   * @param adminLoginDTO adminLogin的DTO
   * @return {@link AdminLoginVO }
   * @description 登录
   */
  @Override
  public AdminLoginVO login(AdminLoginDTO adminLoginDTO) {
    String adminId = adminLoginDTO.getAdminId();
    String adminPassword = adminLoginDTO.getAdminPassword();
    //对密码进行md5加密
    adminPassword = DigestUtils.md5DigestAsHex(adminPassword.getBytes());
    AdminPPC admin = AdminPPC.builder()
        .adminId(Long.valueOf(adminId))
        .adminPassowrd(adminPassword)
        .build();
    //1、根据工人的手机号查询数据库中的数据
    AdminLoginVO adminLoginVO = adminMapper.getAdminById(admin);
    String realPassword = adminMapper.getPasswordById(admin);
    //2、处理各种异常情况（用户名不存在、密码不对）
    if (adminLoginVO == null) {
      throw new LoginFailedException(MessageConstant.ACCOUNT_NOT_FOUND);
    }
    //密码比对

    if (!adminPassword.equals(realPassword)) {
      //密码错误
      throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
    }

    return adminLoginVO;
  }

  /**
   * @param adminPPC admin账户
   * @description 注册
   */
  @Override
  public void register(AdminPPC adminPPC) {
    String adminPassword = adminPPC.getAdminPassowrd();
    //对密码进行md5加密
    adminPassword = DigestUtils.md5DigestAsHex(adminPassword.getBytes());
    adminPPC.setAdminPassowrd(adminPassword);
    adminMapper.addAdmin(adminPPC);
    //TODO 错误处理
  }

  /**
   * @param page
   * @param pageSize
   * @param claimStatus 查询状态
   * @return {@link PageResult }
   * @description 分页查询工人申诉
   */
  @Override
  public PageResult queryWorkerClaimWithStatus(Integer page, Integer pageSize,
      Integer claimStatus) {
    PageHelper.startPage(page, pageSize);
    Page<AdminClaimPageVO> p = adminMapper.pageClaimQuery(claimStatus, ClaimerTypeConstant.workerType);
    return new PageResult(p.getTotal(), p.getResult());
  }

  /**
   * @param page
   * @param pageSize
   * @param claimStatus
   * @return {@link PageResult }
   * @description 分页查询雇主申诉
   */
  @Override
  public PageResult queryEmployerClaimWithStatus(Integer page, Integer pageSize,
      Integer claimStatus) {
    PageHelper.startPage(page, pageSize);
    Page<AdminClaimPageVO> p = adminMapper.pageClaimQuery(claimStatus, ClaimerTypeConstant.employerType);
    return new PageResult(p.getTotal(), p.getResult());
  }

  /**
   * @param claimSolveDTO
   * @description 处理雇主申诉
   */
  @Override
  public void solveEmployerClaim(ClaimSolveDTO claimSolveDTO) {
    Long claimId = claimSolveDTO.getClaimId();
    //如果同意，封禁工人账号，插入处理结果数据
    if (claimSolveDTO.getResult() == 1) {
      Claim claim = Claim.builder()
          .claimId(Long.valueOf(claimId))
          .claimStatus(StatusConstant.ENABLE)
          .claimDetail(claimSolveDTO.getDetail())
          .claimResult(StatusConstant.ENABLE)
          .claimCopeTime(LocalDateTime.now())
          .adminId(BaseContext.getCurrentId())
          .build();
      int handleMethod = adminMapper.getClaimTypeById(claimId);
      agreeClaim(claimId, handleMethod); // 分情况处理
      adminMapper.updateClaimStatus(claim);
    }
    //不同意，插入原因数据
    else if (claimSolveDTO.getResult() == 0) {
      Claim claim = Claim.builder()
          .claimId(Long.valueOf(claimId))
          .claimStatus(StatusConstant.ENABLE) // 已处理申诉
          .claimResult(StatusConstant.DISABLE) // 拒绝
          .claimDetail(claimSolveDTO.getDetail())
          .claimCopeTime(LocalDateTime.now())
          .adminId(BaseContext.getCurrentId())
          .build();
      disagreeClaim(claimId);
      int handleMethod = adminMapper.getClaimTypeById(claimId);
      if (handleMethod == 1) {
        disagreeUpdateTempTask(claimId);
      }
      adminMapper.updateClaimStatus(claim);
    }
  }

  /**
   * @param workerId   工人ID
   * @param recordType 处理类型
   * @description 添加工人申诉记录
   */
  private void claimWorkerRecording(long workerId, String recordType) {

    //扣被举报人的信誉积分
    int credit = adminMapper.getWorkerCreditById(workerId);
    credit -= 5;
    if (credit < 0) {
      credit = 0;
    } else if (credit > 100) {
      credit = 100;
    }
    adminMapper.setWorkerCredit(credit, workerId);
    String recordContent = formatDateTime() + " 因" + recordType + ",信誉度-5";
    long userId = adminMapper.getUserIdByWorkId(workerId);
    Recording recording = Recording.builder()
        .recordingContent(recordContent)
        .userId(userId)
        .recordingType(1)
        .build();
    adminMapper.insertRecording(recording);
  }

  /**
   * @param employerId
   * @param recordType
   * @description 记录雇主申诉信誉
   */
  private void claimEmployerRecording(long employerId, String recordType) {
    //扣被举报人的信誉积分
    int credit = adminMapper.getEmployerCreditById(employerId);
    credit -= 5;
    if (credit < 0) {
      credit = 0;
    } else if (credit > 100) {
      credit = 100;
    }
    adminMapper.setEmployerCredit(credit, employerId);
    String recordContent = formatDateTime() + " 因" + recordType + ",信誉度-5";
    long userId = adminMapper.getUserIdByEmployerId(employerId);
    Recording recording = Recording.builder()
        .recordingContent(recordContent)
        .userId(userId)
        .recordingType(1)
        .build();
    adminMapper.insertRecording(recording);
  }

  /**
   * @param claimSolveDTO 处理申诉
   * @description 不同意，处理tempTask的函数
   */
  @Override
  public void solveWorkerClaim(ClaimSolveDTO claimSolveDTO) {
    Long claimId = claimSolveDTO.getClaimId();
    // 同意
    if (claimSolveDTO.getResult() == 1) {
      Claim claim = Claim.builder()
          .claimId(Long.valueOf(claimId))
          .claimStatus(StatusConstant.ENABLE)
          .claimDetail(claimSolveDTO.getDetail())
          .claimResult(StatusConstant.ENABLE)
          .claimCopeTime(LocalDateTime.now())
          .adminId(BaseContext.getCurrentId())
          .build();
      int handleMethod = adminMapper.getClaimTypeById(claimId);
      agreeClaim(claimId, handleMethod); // 分情况处理
      adminMapper.updateClaimStatus(claim);
    }
    //不同意，插入原因数据
    else if (claimSolveDTO.getResult() == 0) {
      Claim claim = Claim.builder()
          .claimId(Long.valueOf(claimId))
          .claimStatus(StatusConstant.ENABLE) // 已处理申诉
          .claimResult(StatusConstant.DISABLE)
          .claimDetail(claimSolveDTO.getDetail())
          .claimCopeTime(LocalDateTime.now())
          .adminId(BaseContext.getCurrentId())
          .build();
      adminMapper.updateClaimStatus(claim);
      //分情况处理
      disagreeClaim(claimId);
    }
  }

  /**
   * 不同意，处理tempTask的函数
   *
   * @param claimId
   */
  private void disagreeUpdateTempTask(Long claimId) {
    TempTask tempTask = adminMapper.selectTempTaskByClaimId(claimId);
    tempTask.setUpdateTime(LocalDateTime.now());
    tempTask.setAdminId(BaseContext.getCurrentId());
    tempTask.setTempTaskStatus(1);
    adminMapper.updateTempTask(tempTask);
  }

  /**
   * 根据申诉类型处理同意申诉
   *
   * @param claimId      申诉ID
   * @param handleMethod 1 2 3 4 5
   */
  private void agreeClaim(Long claimId, int handleMethod) {

    if (handleMethod == 1) { // 修改订单
      Task task = adminMapper.selectTaskByClaimId(claimId);
      TempTask tempTask = adminMapper.selectTempTaskByTaskId(task.getTaskId());//获取雇主期待修改的信息
      adminMapper.updateTaskStatus(claimId, 2); // 订单状态，进行中
      adminMapper.updateRequirement(tempTask.getRequireBroadDesc(), tempTask.getRequireTitle(),
          tempTask.getRequireDetailDesc(), task.getRequireId());// 修改Requirement的信息
      tempTask.setAdminId(BaseContext.getCurrentId());
      tempTask.setTempTaskStatus(1);
      tempTask.setUpdateTime(LocalDateTime.now());
      adminMapper.updateTempTask(tempTask); //修改tempTask
    } else if (handleMethod == 2) {// 删除订单
      adminMapper.updateTaskStatus(claimId, 4); // 已完成订单
    } else if (handleMethod == 3) { // 不满意订单
      adminMapper.updateTaskStatus(claimId, 4); // 已完成订单
      Long taskId = adminMapper.getTaskIdByClaimId(claimId);
      backToEmployerWallet(taskId);
      createEmployerMoneyRecording(taskId);
      Worker worker = adminMapper.getWorkerById(taskId);
      long workerId = worker.getWorkerId();
      claimWorkerRecording(workerId, "雇主不满意订单");
    } else if (handleMethod == 4) {
      resetTaskStatus(claimId);
      LocalDateTime time = adminMapper.getExpectedEndTimeByClaimId(claimId);
      LocalDateTime newTime = time.plusDays(3); // 延时三天
      adminMapper.updateExpectedEndTimeByClaimId(claimId, newTime);
    } else if (handleMethod == 5) {
      adminMapper.updateTaskStatus(claimId, 4); // 已完成订单
      Long taskId = adminMapper.getTaskIdByClaimId(claimId);
      createWorkerMoneyRecording(taskId);
      updateWorkerWallet(taskId);
      Employer employer = adminMapper.getEmployerById(taskId);
      long employerId = employer.getEmployerId();
      claimEmployerRecording(employerId, "长期不确认");
    }
  }

  /**
   * 处理不同意申诉
   *
   * @param claimId 申诉ID
   */
  private void disagreeClaim(Long claimId) {
    resetTaskStatus(claimId); // 回退task状态
  }


  /**
   * 回退task状态
   *
   * @param claimId 申诉ID
   */
  private void resetTaskStatus(Long claimId) {
    int taskStatus = adminMapper.getTaskStatusByClaimId(claimId);
    int newStatus = taskStatus % 10;
    adminMapper.updateTaskStatus(claimId, newStatus);
  }


  /**
   * 分页按状态查询举报
   */
  @Override
  public PageResult queryComplaintWithStatus(Integer page, Integer pageSize,
      Integer complaintStatus) {
    PageHelper.startPage(page, pageSize);
    Page<AdminComplaintPageVO> p = adminMapper.pageComplaintQuery(complaintStatus);
    return new PageResult(p.getTotal(), p.getResult());
  }

  /**
   * 处理举报
   */
  @Override
  public void solveComplaint(ComplaintSolveDTO complaintSolveDTO) {
    Long complaintId = complaintSolveDTO.getComplaintId();
    //如果同意，封禁雇主账号，插入处理结果数据
    if (complaintSolveDTO.getResult() == 1) {
      long employerId = adminMapper.getEmployerByComplaintId(complaintSolveDTO);
      setEmployerStatus(employerId, StatusConstant.DISABLE);
      Complaint complaint = Complaint.builder()
          .complaintId(Long.valueOf(complaintId))
          .complaintStatus(StatusConstant.ENABLE)
          .complaintResult(MessageConstant.COMPLAINT_AGREE)
          .complaintResultDetail(complaintSolveDTO.getDetail())
          .complaintEndTime(LocalDateTime.now())
          .adminId(BaseContext.getCurrentId())
          .build();
      adminMapper.updateComplaintStatus(complaint);
    }
    //不同意，插入原因数据
    else if (complaintSolveDTO.getResult() == 0) {
      Complaint complaint = Complaint.builder()
          .complaintId(Long.valueOf(complaintId))
          .complaintStatus(StatusConstant.ENABLE)
          .complaintResult(MessageConstant.COMPLAINT_DISAGREE)
          .complaintResultDetail(complaintSolveDTO.getDetail())
          .complaintEndTime(LocalDateTime.now())
          .adminId(BaseContext.getCurrentId())
          .build();
      adminMapper.updateComplaintStatus(complaint);
    }
  }

  /**
   * 获取申诉详情
   */
  @Override
  public AdminClaimDetailVO getClaimDetail(String claimId) {
    AdminClaimDetailVO adminClaimDetailVO = adminMapper.getClaimDetail(claimId);
    return adminClaimDetailVO;
  }

  /**
   * 获取举报详情
   */
  @Override
  public AdminComplaintDetailVO getComplaintDetail(String complaintId) {
    AdminComplaintDetailVO adminComplaintDetailVO = adminMapper.getComplaintDetail(complaintId);
    return adminComplaintDetailVO;
  }

  /**
   * 设置雇主状态
   */
  @Override
  public void setEmployerStatus(long employerId, int status) {
    adminMapper.setEmployerStatus(employerId, status);
  }

  /**
   * 设置工人状态
   */
  @Override
  public void setWorkerStatus(long workerId, int status) {
    adminMapper.setWorkerStatus(workerId, status);
  }

  /**
   * 分页查询雇主
   */
  @Override
  public PageResult queryEmployerWithName(Integer page, Integer pageSize, String userName) {
    PageHelper.startPage(page, pageSize); // Integer status option
    Page<EmployerPageVO> p = adminMapper.pageEmployerQuery(UserConstant.EMPLOYER,
        userName); // 封装类时出错
    return new PageResult(p.getTotal(), p.getResult());
  }

  /**
   * 分页查询工人
   */
  @Override
  public PageResult queryWorkerWithName(Integer page, Integer pageSize, String userName) {
    PageHelper.startPage(page, pageSize); // Integer status option
    Page<WorkerPageVO> p = adminMapper.pageWorkerQuery(UserConstant.WORKER, userName);
    return new PageResult(p.getTotal(), p.getResult());
  }

  /**
   * 雇主钱包金额退款
   */
  public void backToEmployerWallet(Long taskId) {
    Employer employer = adminMapper.getEmployerById(taskId);
    Requirement requirement = adminMapper.getRequirementById(taskId);
    Float employerCount = employer.getEmployerCount() + requirement.getRequireAmount();
    Long employerId = employer.getEmployerId();
    int taskStatus = 1;
    adminMapper.updateEmployerWallet(employerId, employerCount);
    adminMapper.updateTaskStatus(taskId, taskStatus);
  }

  /**
   * 工人钱包金额变化
   */
  public void updateWorkerWallet(Long taskId) {
    Worker worker = adminMapper.getWorkerById(taskId);
    Requirement requirement = adminMapper.getRequirementById(taskId);
    Float workerCount = worker.getWorkerCount() + requirement.getRequireAmount();
    Long workerId = worker.getWorkerId();
    adminMapper.updateWorkerWallet(workerId, workerCount);
  }

  /**
   * 雇主创建金额变化记录
   */
  public void createEmployerMoneyRecording(Long taskId) {

    Requirement requirement = adminMapper.getRequirementById(taskId);
    Employer employer = adminMapper.getEmployerById(taskId);
    Recording recording = Recording.builder()
        .recordingContent(
            formatDateTime() + " 关闭" + " '" + requirement.getRequireTitle() + "' 订单,钱包金额返回账户+"
                + requirement.getRequireAmount() + "元")
        .recordingType(0)
        .userId(employer.getUserId())
        .build();
    adminMapper.createMoneyRecording(recording);
  }

  /**
   * 工人创建金额变化记录
   */
  public void createWorkerMoneyRecording(Long taskId) {
    Requirement requirement = adminMapper.getRequirementById(taskId);
    Worker worker = adminMapper.getWorkerById(taskId);
    Recording recording = Recording.builder()
        .recordingContent(
            formatDateTime() + " 完成" + " '" + requirement.getRequireTitle() + "' 订单,钱包金额+"
                + requirement.getRequireAmount() + "元")
        .recordingType(0)
        .userId(worker.getUserId())
        .build();
    adminMapper.createMoneyRecording(recording);
  }

  private static String formatDateTime() {
    // 获取当前时间
    LocalDateTime now = LocalDateTime.now();

    // 定义日期时间格式
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    // 格式化LocalDateTime对象
    String formattedDateTime = now.format(formatter);
    return formattedDateTime;
  }
}
